package com.fs.files.util;

import com.fs.core.util.CollectionUtil;
import com.fs.core.util.StringUtil;
import com.fs.files.annotation.CimeField;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class CimeUtil {

    /**
     * 获取类名称
     * 例：<cim:Equipment::南网>解析为Equipment
     * @param singleLine cime文件行字符串
     * @return
     */
    public static String getCimClassName(String singleLine){
        if(singleLine.contains("::")){
            String[] temp = singleLine.split("::");
            String className = temp[0].substring(5);
            return className;
        }
        return singleLine;
    }

    /**
     * 获取类对象
     * @param classPath 类路径
     * @param className 类名称
     * @return
     */
    public static Class getInstance(String classPath, String className) throws ClassNotFoundException {
        if(StringUtil.isNotEmpty(classPath)){
            className = getClassName(className);
            return Class.forName(classPath + "." + className);
        }
        return Class.forName(className);
    }

    /**
     * 解析类名称，cime文件类名称和实体类名称不一致需要转换
     * Equipment == CimEquipmentInfo
     * @param className
     * @return
     */
    public static String getClassName(String className){
        return "Cim" + className + "Info";
    }

    /**
     * 获取cime数据封装成集合对象
     * @param cls 类对象
     * @param properties 类属性 \t 分割
     * @param valueList 类数据集合 stirng \t 分割
     * @return
     */
    public static List<Object> getObjectList(Class cls, String properties, List<String> valueList) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        List<Object> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        Field[] fields = cls.getDeclaredFields();
        for(Field field : fields){
            //打开私有访问
            field.setAccessible(true);
            //判断字段上是否有注解
            boolean hasRPS = field.isAnnotationPresent(CimeField.class);
            if(hasRPS){
                CimeField rps = field.getAnnotation(CimeField.class);
                String rpsName = rps.name();
                //属性名称
                String attrName =  field.getName();
                map.put(rpsName, attrName);
            }
        }
        String [] arrProperties = properties.split("\t");
        for(String value : valueList){
            //实例化对象
            Object obj = cls.newInstance();
            String [] arrValue = value.split("\t");
            for(int i=0;i<arrProperties.length;i++){
                if(map.containsKey(arrProperties[i])){
                    String name = map.get(arrProperties[i]);
                    Field f = cls.getDeclaredField(name);
                    f.setAccessible(true);
                    String type = f.getGenericType().toString();
                    if("class java.lang.Float".equals(type)){
                        f.set(obj, Float.valueOf(arrValue[i]));
                    }
                    else if("class java.lang.Boolean".equals(type)){
                        f.set(obj, Boolean.valueOf(arrValue[i]));
                    }
                    else if("class java.lang.Integer".equals(type)){
                        f.set(obj, Integer.valueOf(arrValue[i]));
                    }
                    else if("class java.lang.Double".equals(type)){
                        f.set(obj, Double.valueOf(arrValue[i]));
                    }
                    else {
                        f.set(obj, "NULL".equalsIgnoreCase(arrValue[i]) ? "" : arrValue[i]);
                    }
                }
            }
            list.add(obj);
        }
        return list;
    }

//**************************************上读下写****************************//

    /**
     * cim数据描述文件的声明
     * @param obj 类实例
     * @return
     */
    public static String writeCimHeader(Object obj){
        List<String> listStr = new ArrayList<>();
        listStr.add("<!");
        Field[] fields = obj.getClass().getDeclaredFields();
        for(Field field : fields){
            //打开私有访问
            field.setAccessible(true);
            //判断字段上是否有注解
            boolean fieldHasAnno = field.isAnnotationPresent(CimeField.class);
            if(fieldHasAnno){
                CimeField fieldAnno = field.getAnnotation(CimeField.class);
                //输出注解属性名称
                String rpsName = fieldAnno.name();
                //属性名称
                String attrName =  field.getName();
                try {
                    String str = readAttrAndValue(obj, rpsName, attrName);
                    listStr.add(str);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        listStr.add("!>");
        return String.join("\t", listStr);
    }

    /**
     * 写入cime文件数据
     * @param list 数据集合
     * @param cls 数据类
     * @return
     */
    public static String writeCimData(List<?> list, Class cls){
        // 拼接数据
        StringBuffer stringBuffer = new StringBuffer();
        // 类名解析
        String cimClassName = cls.getSimpleName();
        // 判断类上是否有次注解
        boolean hasRPS = cls.isAnnotationPresent(CimeField.class);
        if(hasRPS) {
            // 获取类上的注解名称
            CimeField rps = (CimeField) cls.getAnnotation(CimeField.class);
            cimClassName = rps.name();
        }
        //类属性，按规范要求以‘@Num’开始
        String attributeStr ="\n"+"@Num";
        //类属性，按规范要求独占一行，以‘@Num’开始
        String noteStr = "\n"+"//序号";
        //类属性值
        String valueList = "";
        Field[] fields = cls.getDeclaredFields();
        for(Field field : fields){
            //打开私有访问
            field.setAccessible(true);
            //判断字段上是否有注解
            boolean fieldHasAnno = field.isAnnotationPresent(CimeField.class);
            if(fieldHasAnno){
                CimeField fieldAnno = field.getAnnotation(CimeField.class);
                //输出注解属性名称
                String rpsName = fieldAnno.name();
                attributeStr += "\t"+rpsName;
                //输出注解属性备注
                String rpsNote = fieldAnno.notes();
                noteStr += "\t"+rpsNote;
            }
        }
        if(CollectionUtil.isNotEmpty(list)){
            int num = 1;
            for(Object object : list){
                //集合行数据，按规范独占一行，以‘#’开始
                String tr = "\n#"+num++;
                for(Field field : fields){
                    //打开私有访问
                    field.setAccessible(true);
                    //判断字段上是否有注解
                    boolean fieldHasAnno = field.isAnnotationPresent(CimeField.class);
                    if(fieldHasAnno){
                        //属性名称
                        String attrName =  field.getName();
                        //属性值，按规范默认为 NULL
                        String attrValue = "NULL";
                        try {
                            //获取属性值
                            Object obj = readAttributeValue(object, attrName);
                            if(null != obj){
                                attrValue = String.valueOf(obj).equals("") ? attrValue : String.valueOf(obj);
                            }
                            tr += "\t"+attrValue;
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                valueList += tr;
            }
        }
        //拼接cime数据
        stringBuffer.append(getCimClassNameBegin(cimClassName, "南网"));
        stringBuffer.append(attributeStr);
        stringBuffer.append(noteStr);
        stringBuffer.append(valueList);
        stringBuffer.append(getCimClassNameEnd(cimClassName, "南网"));
        return stringBuffer.toString();
    }

    /**
     * 根据属性，获取get方法
     * @param ob 对象
     * @param name 属性名
     * @return
     * @throws Exception
     */
    public static Object readAttributeValue(Object ob, String name)throws Exception{
        Method[] m = ob.getClass().getMethods();
        for(int i = 0;i < m.length;i++){
            if(("get"+name).toLowerCase().equals(m[i].getName().toLowerCase())){
                return m[i].invoke(ob);
            }
        }
        return null;
    }

    /**
     * 封装cim实体类起始行标识，例如：<cim:Substation::云南>
     * @param className 类标识名称
     * @param dispatch 调度区域名称
     * @return
     */
    public static String getCimClassNameBegin(String className, String dispatch){
        return "\n"+"<cim:"+className+"::"+dispatch+">";
    }

    /**
     * 封装cim实体类结束行标识，例如：</Substation::云南>
     * @param className 类标识名称
     * @param dispatch 调度区域名称
     * @return
     */
    public static String getCimClassNameEnd(String className, String dispatch){
        return "\n</"+className+"::"+dispatch+">";
    }

    /**
     * 获取属性值
     * @param object 类对象
     * @param rspName 注解属性名
     * @param attrName 类属性名
     * @return
     * @throws Exception
     */
    public static String readAttrAndValue(Object object, String rspName, String attrName)throws Exception{
        Method[] m = object.getClass().getMethods();
        for(int i = 0;i < m.length;i++){
            if(("get"+attrName).toLowerCase().equals(m[i].getName().toLowerCase())){
                Object obj = m[i].invoke(object);
                String value = "";
                if(obj!=null){
                    value = String.valueOf(obj);
                }
                return rspName+"="+value;
            }
        }
        return "";
    }

}
